package com.adjy.pathbuilders.rendering.loading;

import java.io.IOException;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.adjy.pathbuilders.rendering.DisplayConverter;
import com.adjy.pathbuilders.rendering.Point;

public class ImageFactory {
	
	private final static String PATHS_FILE = "images_file";
	
	private HashMap<String, Bitmap> images; // id -> Bitmap
	private HashMap<String, ImageDescription> paths; // id -> description
	private Context context;
	
	public ImageFactory(Context c) {
		this.context = c;
		images = new HashMap<String, Bitmap>();
		paths = new HashMap<String, ImageDescription>();
		getPaths(PATHS_FILE);
	}
	
	public Bitmap getImage(String id) {
		if (images.containsKey(id)) {
			if (images.get(id).isRecycled()) {
				Log.e("getImage()", id + " has been recycled... loading again...");
				loadImages(id);
			}
			
			return images.get(id);
		}
		
		if (paths.containsKey(id)) {
			Log.i("getImage()", id + " is not loaded yet... loading on the fly...");
			loadImages(id);
			return images.get(id);
		}
		
		Log.e("getImage()", id + " is not specified on the images file!");
		return null;
	}
	
	public void releaseImages(String... ids) {
		for (String id : ids) {
			if (images.containsKey(id)) {
				if (images.get(id) != null) {
					images.get(id).recycle();
					images.remove(id);
				}
			}
		}
	}

	public void loadImages(String... ids) {
		for (String id : ids) {
			loadImageById(id);
		}
	}
	
	protected Context getContext() {
		return context;
	}
	
	private void loadImageById(String id) {
		if (!images.containsKey(id)) {
			if (paths.containsKey(id)) {
				
				Bitmap b = loadImageByDescription(paths.get(id));
				if (b != null) {
					images.put(id, b);
				}
			} else {
				Log.e("Load Image by ID", "ID: " + id + " has not a path specified");
			}
		}
	}
	
	private Bitmap loadImageByDescription(ImageDescription iDescription) {
		String path = iDescription.getPath();
		
		int width = iDescription.getWidth();
		int height = iDescription.getHeight();
		
		if (width < 1 || height < 1) { // Images that doesnt has dimensions
			Point screenSize = DisplayConverter.getDisplaySize();
			width = (int) screenSize.getX();
			height = (int) screenSize.getY();
		} else {
			width = (int) (width * DisplayConverter.getScreenRatioWidth());
			height = (int) (height * DisplayConverter.getScreenRatioHeight());
		}
		
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inPreferredConfig = Bitmap.Config.ARGB_8888;
		
		try {
			
			Bitmap b = BitmapFactory.decodeStream(context.getAssets().open(path), null, options);
			if (b.getWidth() == width && b.getHeight() == height)
				return b;
			Bitmap scaled =  Bitmap.createScaledBitmap(b, width, height, true);

			b.recycle();
			return scaled;

		} catch (IOException e) {
			Log.e("Failed to Load Bitmap", "Path: " + path);
			e.printStackTrace();
		}
		
		return null;
	}
	
	private void getPaths(String pathsFile) {
		
		try {
			HashMap<String, String[]> pathsFileContent =
					ImageFileParser.parseImageFile(context.getAssets().open(PATHS_FILE));
			
			for (String id : pathsFileContent.keySet()) {
				
				this.paths.put(id,
						new ImageDescription(pathsFileContent.get(id)));
				
			}
		} catch (IOException e) {
			Log.e("Get Paths", "Failed Opening Paths File");
			e.printStackTrace();
		}
	}
}
